home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagg_m.zip / GRAPHICS.SWG / 0029_TWEAKED! Graph unit.pas < prev    next >
Pascal/Delphi Source File  |  1993-08-27  |  18KB  |  911 lines

  1. {$A-,B-,D+,E-,F-,G+,I-,L+,N-,O-,R-,S-,V-,X+} {TP 6.0 & 286 required!}
  2. Unit x320x240;
  3.  
  4. {
  5.  Sean Palmer, 1993
  6.  released to the Public Domain
  7.  in tweaked modes, each latch/bit plane contains the entire 8-bit pixel.
  8.  the sequencer map mask determines which plane (pixel) to update, and, when
  9.  reading, the read map select reg determines which plane (pixel) to read.
  10.  almost exactly opposite from regular vga 16-color modes which is why I never
  11.  could get my routines to work For BOTH modes. 8)
  12.  
  13.   # = source screen pixel
  14.   Normal 16-color         Tweaked 256-color
  15.  
  16.       Bit Mask                Bit Mask
  17.       76543210                33333333
  18.  Map  76543210           Map  22222222
  19.  Mask 76543210           Mask 11111111
  20.       76543210                00000000
  21.  
  22.   Functional equivalents
  23.       Bit Mask        =       Seq Map Mask
  24.       Seq Map Mask    =       Bit Mask
  25. }
  26.  
  27.  
  28. Interface
  29.  
  30. Var
  31.   color : Byte;
  32.  
  33. Const
  34.  xRes    = 320;
  35.  yRes    = 240;   {displayed screen size}
  36.  xMax    = xRes - 1;
  37.  yMax    = yRes - 1;
  38.  xMid    = xMax div 2;
  39.  yMid    = yMax div 2;
  40.  vxRes   = 512;
  41.  vyRes   = $40000 div vxRes; {virtual screen size}
  42.  nColors = 256;
  43.  tsx : Byte = 8;
  44.  tsy : Byte = 8;  {tile size}
  45.  
  46.  
  47. Procedure plot(x, y : Integer);
  48. Function  scrn(x, y : Integer) : Byte;
  49.  
  50. Procedure hLin(x, x2, y : Integer);
  51. Procedure vLin(x, y, y2 : Integer);
  52. Procedure rect(x, y, x2, y2 : Integer);
  53. Procedure pane(x, y, x2, y2 : Integer);
  54.  
  55. Procedure line(x, y, x2, y2 : Integer);
  56. Procedure oval(xc, yc, a, b : Integer);
  57. Procedure disk(xc, yc, a, b : Integer);
  58. Procedure fill(x, y : Integer);
  59.  
  60. Procedure putTile(x, y : Integer; p : Pointer);
  61. Procedure overTile(x, y : Integer; p : Pointer);
  62. Procedure putChar(x, y : Integer; p : Word);
  63.  
  64. Procedure setColor(color, r, g, b : Byte);
  65. {rgb vals are from 0-63}
  66. Function  getColor(color : Byte) : LongInt;
  67. {returns $00rrggbb format}
  68. Procedure setPalette(color : Byte; num : Word; Var rgb);
  69. {rgb is list of 3-Byte rgb vals}
  70. Procedure getPalette(color : Byte; num : Word; Var rgb);
  71.  
  72. Procedure clearGraph;
  73. Procedure setWriteMode(f : Byte);
  74. Procedure waitRetrace;
  75. Procedure setWindow(x, y : Integer);
  76.  
  77. {XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}
  78.  
  79. Implementation
  80.  
  81. Const
  82.   vSeg     = $A000;        {video segment}
  83.   vxBytes  = vxRes div 4;  {Bytes per virtual scan line}
  84.   seqPort  = $3C4;   {Sequencer}
  85.   gcPort   = $3CE;    {Graphics Controller}
  86.   attrPort = $3C0;   {attribute Controller}
  87.  
  88.   tableReadIndex    = $3C7;
  89.   tableWriteIndex   = $3C8;
  90.   tableDataRegister = $3C9;
  91.  
  92.   CrtcRegLen   = 10;
  93.   CrtcRegTable : Array [1..CrtcRegLen] of Word =
  94.     ($0D06, $3E07, $4109, $EA10, $AC11, $DF12, $0014, $E715, $0616, $E317);
  95.  
  96.  
  97.  
  98. Var
  99.   CrtcPort   : Word;  {Crt controller}
  100.   oldMode    : Byte;
  101.   ExitSave   : Pointer;
  102.   input1Port : Word;  {Crtc Input Status Reg #1=CrtcPort+6}
  103.   fillVal    : Byte;
  104.  
  105. Type
  106.  tRGB = Record
  107.    r, g, b : Byte;
  108.  end;
  109.  
  110. {XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}
  111.  
  112. Procedure clearGraph; Assembler;
  113. Asm
  114.   mov ax, vSeg
  115.   mov es, ax
  116.   mov dx, seqPort
  117.   mov ax, $0F02
  118.   out dx, ax {enable whole map mask}
  119.   xor di, di
  120.   mov cx, $8000 {screen size in Words}
  121.   cld
  122.   mov al, color
  123.   mov ah, al
  124.   repz stosw {clear screen}
  125. end;
  126.  
  127. Procedure setWriteMode(f : Byte); Assembler;
  128. Asm {copy/and/or/xor modes}
  129.   mov ah, f
  130.   shl ah, 3
  131.   mov al, 3
  132.   mov dx, gcPort
  133.   out dx, ax {Function select reg}
  134. end;
  135.  
  136. Procedure waitRetrace; Assembler;
  137. Asm
  138.   mov  dx, CrtcPort
  139.   add  dx, 6 {find Crt status reg (input port #1)}
  140.  @L1:
  141.   in   al, dx
  142.   test al, 8
  143.   jnz  @L1;  {wait For no v retrace}
  144.  @L2:
  145.   in   al, dx
  146.   test al, 8
  147.   jz   @L2 {wait For v retrace}
  148.  end;
  149.  
  150.  
  151. {
  152.  Since a virtual screen can be larger than the actual screen, scrolling is
  153.  possible.  This routine sets the upper left corner of the screen to the
  154.  specified pixel. Make sure 0 <= x <= vxRes - xRes, 0 <= y <= vyRes - yRes
  155. }
  156. Procedure setWindow(x, y : Integer); Assembler;
  157. Asm
  158.   mov  ax, vxBytes
  159.   mul  y
  160.   mov  bx, x
  161.   mov  cl, bl
  162.   shr  bx, 2
  163.   add  bx, ax     {bx=Ofs of upper left corner}
  164.   mov  dx, input1Port
  165.  @L:
  166.   in   al, dx
  167.   test al, 8
  168.   jnz  @L  {wait For no v retrace}
  169.   sub  dx, 6  {CrtC port}
  170.   mov  al, $D
  171.   mov  ah, bl
  172.   cli {these values are sampled at start of retrace}
  173.   out  dx, ax  {lo Byte of display start addr}
  174.   dec  al
  175.   mov  ah, bh
  176.   out  dx, ax    {hi Byte}
  177.   sti
  178.   add  dx, 6
  179.  @L2:
  180.   in   al, dx
  181.   test al, 8
  182.   jz   @L2  {wait For v retrace}
  183.   {this also resets Attrib flip/flop}
  184.   mov  dx, attrPort
  185.   mov  al, $33
  186.   out  dx, al   {Select Pixel Pan Register}
  187.   and  cl, 3
  188.   mov  al, cl
  189.   shl  al, 1
  190.   out  dx, al   {Shift is For 256 Color Mode}
  191. end;
  192.  
  193. {XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}
  194.  
  195. Procedure plot(x, y : Integer); Assembler;
  196. Asm
  197.   mov   ax, vSeg
  198.   mov   es, ax
  199.   mov   di, x
  200.   mov   cx, di
  201.   shr   di, 2
  202.   mov   ax, vxBytes
  203.   mul   y
  204.   add   di, ax
  205.   mov   ax, $0102
  206.   and   cl, 3
  207.   shl   ah, cl
  208.   mov   dx, seqPort
  209.   out   dx, ax {set bit mask}
  210.   mov   al, color
  211.   stosb
  212. end;
  213.  
  214. Function scrn(x, y : Integer) : Byte; Assembler;
  215. Asm
  216.   mov ax, vSeg
  217.   mov es, ax
  218.   mov di, x
  219.   mov cx, di
  220.   shr di, 2
  221.   mov ax, vxBytes
  222.   mul y
  223.   add di, ax
  224.   and cl, 3
  225.   mov ah, cl
  226.   mov al, 4
  227.   mov dx, gcPort
  228.   out dx, ax      {Read Map Select register}
  229.   mov al, es:[di]  {get the whole plane}
  230. end;
  231.  
  232. Procedure hLin(x, x2, y : Integer); Assembler;
  233. Asm
  234.   mov   ax, vSeg
  235.   mov   es, ax
  236.   cld
  237.   mov   ax, vxBytes
  238.   mul   y
  239.   mov   di, ax {base of scan line}
  240.   mov   bx, x
  241.   mov   cl, bl
  242.   shr   bx, 2
  243.   mov   dx, x2
  244.   mov   ch, dl
  245.   shr   dx, 2
  246.   and   cx, $0303
  247.   sub   dx, bx     {width in Bytes}
  248.   add   di, bx     {offset into video buffer}
  249.   mov   ax, $FF02
  250.   shl   ah, cl
  251.   and   ah, $0F {left edge mask}
  252.   mov   cl, ch
  253.   mov   bh, $F1
  254.   rol   bh, cl
  255.   and   bh, $0F {right edge mask}
  256.   mov   cx, dx
  257.   or    cx, cx
  258.   jnz   @LEFT
  259.   and   ah, bh                  {combine left & right bitmasks}
  260.  @LEFT:
  261.   mov   dx, seqPort
  262.   out   dx, ax
  263.   inc   dx
  264.   mov   al, color
  265.   stosb
  266.   jcxz  @EXIT
  267.   dec   cx
  268.   jcxz  @RIGHT
  269.   mov   al, $0F
  270.   out   dx, al     {skipped if cx=0,1}
  271.   mov   al, color
  272.   repz  stosb   {fill middle Bytes}
  273.  @RIGHT:
  274.   mov   al, bh
  275.   out   dx, al       {skipped if cx=0}
  276.   mov   al, color
  277.   stosb
  278.  @EXIT:
  279. end;
  280.  
  281. Procedure vLin(x, y, y2 : Integer); Assembler;
  282. Asm
  283.   mov ax, vSeg
  284.   mov es, ax
  285.   cld
  286.   mov di, x
  287.   mov cx, di
  288.   shr di, 2
  289.   mov ax, vxBytes
  290.   mul y
  291.   add di, ax
  292.   mov ax, $102
  293.   and cl, 3
  294.   shl ah, cl
  295.   mov dx, seqPort
  296.   out dx, ax
  297.   mov cx, y2
  298.   sub cx, y
  299.   inc cx
  300.   mov al, color
  301.  @DOLINE:
  302.   mov bl, es:[di]
  303.   stosb
  304.   add di, vxBytes-1
  305.   loop @DOLINE
  306. end;
  307.  
  308. Procedure rect(x, y, x2, y2 : Integer);
  309. Var
  310.   i : Word;
  311. begin
  312.   hlin(x, pred(x2), y);
  313.   hlin(succ(x), x2, y2);
  314.   vlin(x, succ(y), y2);
  315.   vlin(x2, y, pred(y2));
  316. end;
  317.  
  318. Procedure pane(x, y, x2, y2 : Integer);
  319. Var
  320.   i : Word;
  321. begin
  322.   For i := y2 downto y do
  323.     hlin(x, x2, i);
  324. end;
  325.  
  326. Procedure line(x, y, x2, y2:Integer);
  327. Var
  328.   d, dx, dy,
  329.   ai, bi, xi, yi : Integer;
  330. begin
  331.   if(x < x2) then
  332.   begin
  333.     xi := 1;
  334.     dx := x2 - x;
  335.   end
  336.   else
  337.   begin
  338.     xi := -1;
  339.     dx := x - x2;
  340.   end;
  341.   if (y < y2) then
  342.   begin
  343.     yi := 1;
  344.     dy := y2 - y;
  345.   end
  346.   else
  347.   begin
  348.     yi := -1;
  349.     dy := y - y2;
  350.   end;
  351.   plot(x, y);
  352.   if dx > dy then
  353.   begin
  354.     ai := (dy - dx) * 2;
  355.     bi := dy * 2;
  356.     d  := bi - dx;
  357.     Repeat
  358.       if (d >= 0) then
  359.       begin
  360.         inc(y, yi);
  361.         inc(d, ai);
  362.       end
  363.       else
  364.         inc(d, bi);
  365.       inc(x, xi);
  366.       plot(x, y);
  367.     Until (x = x2);
  368.   end
  369.   else
  370.   begin
  371.     ai := (dx - dy) * 2;
  372.     bi := dx * 2;
  373.     d  := bi - dy;
  374.     Repeat
  375.       if (d >= 0) then
  376.       begin
  377.         inc(x, xi);
  378.         inc(d, ai);
  379.       end
  380.       else
  381.         inc(d, bi);
  382.       inc(y, yi);
  383.       plot(x, y);
  384.     Until (y = y2);
  385.   end;
  386. end;
  387.  
  388. Procedure oval(xc, yc, a, b : Integer);
  389. Var
  390.   x, y      : Integer;
  391.   aa, aa2,
  392.   bb, bb2,
  393.   d, dx, dy : LongInt;
  394. begin
  395.   x := 0;
  396.   y := b;
  397.   aa := LongInt(a) * a;
  398.   aa2 := 2 * aa;
  399.   bb := LongInt(b) * b;
  400.   bb2 := 2 * bb;
  401.   d := bb - aa * b + aa div 4;
  402.   dx := 0;
  403.   dy := aa2 * b;
  404.   plot(xc, yc - y);
  405.   plot(xc, yc + y);
  406.   plot(xc - a, yc);
  407.   plot(xc + a, yc);
  408.   While (dx < dy) do
  409.   begin
  410.     if(d > 0) then
  411.     begin
  412.       dec(y);
  413.       dec(dy, aa2);
  414.       dec(d, dy);
  415.     end;
  416.     inc(x);
  417.     inc(dx, bb2);
  418.     inc(d, bb + dx);
  419.     plot(xc + x, yc + y);
  420.     plot(xc - x, yc + y);
  421.     plot(xc + x, yc - y);
  422.     plot(xc - x, yc - y);
  423.   end;
  424.  
  425.   inc(d, (3 * (aa - bb) div 2 - (dx + dy)) div 2);
  426.  
  427.   While (y > 0) do
  428.   begin
  429.     if (d < 0) then
  430.     begin
  431.       inc(x);
  432.       inc(dx, bb2);
  433.       inc(d, bb + dx);
  434.     end;
  435.     dec(y);
  436.     dec(dy, aa2);
  437.     inc(d, aa - dy);
  438.     plot(xc + x, yc + y);
  439.     plot(xc - x, yc + y);
  440.     plot(xc + x, yc - y);
  441.     plot(xc - x, yc - y);
  442.   end;
  443. end;
  444.  
  445. Procedure disk(xc, yc, a, b:Integer);
  446. Var
  447.   x, y      : Integer;
  448.   aa, aa2,
  449.   bb, bb2,
  450.   d, dx, dy : LongInt;
  451. begin
  452.   x   := 0;
  453.   y   := b;
  454.   aa  := LongInt(a) * a;
  455.   aa2 := 2 * aa;
  456.   bb  := LongInt(b) * b;
  457.   bb2 := 2 * bb;
  458.   d   := bb - aa * b + aa div 4;
  459.   dx  := 0;
  460.   dy  := aa2 * b;
  461.  
  462.   vLin(xc, yc - y, yc + y);
  463.  
  464.   While (dx < dy) do
  465.   begin
  466.     if (d > 0) then
  467.     begin
  468.       dec(y);
  469.       dec(dy, aa2);
  470.       dec(d, dy);
  471.     end;
  472.     inc(x);
  473.     inc(dx, bb2);
  474.     inc(d, bb + dx);
  475.     vLin(xc - x, yc - y, yc + y);
  476.     vLin(xc + x, yc - y, yc + y);
  477.   end;
  478.  
  479.   inc(d, (3 * (aa - bb) div 2 - (dx + dy)) div 2);
  480.  
  481.   While (y >= 0) do
  482.   begin
  483.     if (d < 0) then
  484.     begin
  485.       inc(x);
  486.       inc(dx, bb2);
  487.       inc(d, bb + dx);
  488.       vLin(xc - x, yc - y, yc + y);
  489.       vLin(xc + x, yc - y, yc + y);
  490.     end;
  491.     dec(y);
  492.     dec(dy, aa2);
  493.     inc(d, aa - dy);
  494.   end;
  495. end;
  496.  
  497. {This routine only called by fill}
  498. Function lineFill(x, y, d, prevXL, prevXR : Integer) : Integer;
  499. Var
  500.   xl, xr, i : Integer;
  501. Label
  502.   _1, _2, _3;
  503. begin
  504.   xl := x;
  505.   xr := x;
  506.  
  507.   Repeat
  508.     dec(xl);
  509.   Until (scrn(xl, y) <> fillVal) or (xl < 0);
  510.  
  511.   inc(xl);
  512.  
  513.   Repeat
  514.     inc(xr);
  515.   Until (scrn(xr, y) <> fillVal) or (xr > xMax);
  516.  
  517.   dec(xr);
  518.   hLin(xl, xr, y);
  519.   inc(y, d);
  520.  
  521.   if Word(y) <= yMax then
  522.   For x := xl to xr do
  523.     if (scrn(x, y) = fillVal) then
  524.     begin
  525.       x := lineFill(x, y, d, xl, xr);
  526.       if Word(x) > xr then
  527.         Goto _1;
  528.     end;
  529.  
  530.   _1 :
  531.  
  532.   dec(y, d + d);
  533.   Asm
  534.     neg d;
  535.   end;
  536.   if Word(y) <= yMax then
  537.   begin
  538.   For x := xl to prevXL do
  539.     if (scrn(x, y) = fillVal) then
  540.     begin
  541.       i := lineFill(x, y, d, xl, xr);
  542.       if Word(x) > prevXL then
  543.         Goto _2;
  544.     end;
  545.  
  546.     _2 :
  547.  
  548.     for x := prevXR to xr do
  549.       if (scrn(x, y) = fillVal) then
  550.       begin
  551.         i := lineFill(x, y, d, xl, xr);
  552.         if Word(x) > xr then
  553.           Goto _3;
  554.       end;
  555.  
  556.       _3 :
  557.  
  558.       end;
  559.  
  560.   lineFill := xr;
  561. end;
  562.  
  563. Procedure fill(x, y : Integer);
  564. begin
  565.   fillVal := scrn(x, y);
  566.   if fillVal <> color then
  567.     lineFill(x, y, 1, x, x);
  568. end;
  569.  
  570.  
  571. {XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}
  572.  
  573. Procedure putTile(x, y : Integer; p : Pointer); Assembler;
  574. Asm
  575.   push  ds
  576.   lds   si, p
  577.   mov   ax, vSeg
  578.   mov   es, ax
  579.   mov   di, x
  580.   mov   cx, di
  581.   shr   di, 2
  582.   mov   ax, vxBytes
  583.   mul   y
  584.   add   di, ax
  585.   mov   ax, $102
  586.   and   cl, 3
  587.   shl   ah, cl      {make bit mask}
  588.   mov   dx, seqPort
  589.   mov   bh, tsy
  590.  @DOLINE:
  591.   mov   cl, tsx
  592.   xor   ch, ch
  593.   push  ax
  594.   push  di    {save starting bit mask}
  595.  @LOOP:
  596.   {mov al, 2}
  597.   out   dx, ax
  598.   shl   ah, 1       {give it some time to respond}
  599.   mov   bl, es:[di]
  600.   movsb
  601.   dec   di
  602.   test  ah, $10
  603.   jz    @SAMEByte
  604.   mov   ah, 1
  605.   inc   di
  606.  @SAMEByte:
  607.   loop  @LOOP
  608.   pop   di
  609.   add   di, vxBytes
  610.   pop   ax {start of next line}
  611.   dec   bh
  612.   jnz   @DOLINE
  613.   pop   ds
  614. end;
  615.  
  616. Procedure overTile(x, y : Integer; p : Pointer); Assembler;
  617. Asm
  618.   push  ds
  619.   lds   si, p
  620.   mov   ax, vSeg
  621.   mov   es, ax
  622.   mov   di, x
  623.   mov   cx, di
  624.   shr   di, 2
  625.   mov   ax, vxBytes
  626.   mul   y
  627.   add   di, ax
  628.   mov   ax, $102
  629.   and   cl, 3
  630.   shl   ah, cl      {make bit mask}
  631.   mov   bh, tsy
  632.   mov   dx, seqPort
  633.  @DOLINE:
  634.   mov   ch, tsx
  635.   push  ax
  636.   push  di    {save starting bit mask}
  637.  @LOOP:
  638.   mov   al, 2
  639.   mov   dx, seqPort
  640.   out   dx, ax
  641.   shl   ah, 1
  642.   xchg  ah, cl
  643.   mov   al, 4
  644.   mov   dl, gcPort and $FF
  645.   out   dx, ax
  646.   xchg  ah, cl
  647.   inc   cl
  648.   and   cl, 3
  649.   lodsb
  650.   or    al, al
  651.   jz    @SKIP
  652.   mov   bl, es:[di]
  653.   cmp   bl, $C0
  654.   jae   @SKIP
  655.   stosb
  656.   dec   di
  657.  @SKIP:
  658.   test  ah, $10
  659.   jz    @SAMEByte
  660.   mov   ah, 1
  661.   inc   di
  662.  @SAMEByte:
  663.   dec   ch
  664.   jnz   @LOOP
  665.   pop   di
  666.   add   di, vxBytes
  667.   pop   ax {start of next line}
  668.   dec   bh
  669.   jnz   @DOLINE
  670.   pop   ds
  671. end;
  672.  
  673. {won't handle Chars wider than 1 Byte}
  674. Procedure putChar(x, y : Integer; p : Word); Assembler;
  675. Asm
  676.   mov   si, p  {offset of Char in DS}
  677.   mov   ax, vSeg
  678.   mov   es, ax
  679.   mov   di, x
  680.   mov   cx, di
  681.   shr   di, 2
  682.   mov   ax, vxBytes
  683.   mul   y
  684.   add   di, ax
  685.   mov   ax, $0102
  686.   and   cl, 3
  687.   shl   ah, cl      {make bit mask}
  688.   mov   dx, seqPort
  689.   mov   cl, tsy
  690.   xor   ch, ch
  691.  @DOLINE:
  692.   mov   bl, [si]
  693.   inc   si
  694.   push  ax
  695.   push  di    {save starting bit mask}
  696.  @LOOP:
  697.   mov   al, 2
  698.   out   dx, ax
  699.   shl   ah, 1
  700.   shl   bl, 1
  701.   jnc   @SKIP
  702.   mov   al, color
  703.   mov   es:[di], al
  704.  @SKIP:
  705.   test  ah, $10
  706.   jz    @SAMEByte
  707.   mov   ah, 1
  708.   inc   di
  709.  @SAMEByte:
  710.   or    bl, bl
  711.   jnz   @LOOP
  712.   pop   di
  713.   add   di, vxBytes
  714.   pop   ax {start of next line}
  715.   loop  @DOLINE
  716. end;
  717.  
  718. {XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}
  719.  
  720. Procedure setColor(color, r, g, b : Byte); Assembler;
  721. Asm {set DAC color}
  722.   mov  dx, tableWriteIndex
  723.   mov  al, color
  724.   out  dx, al
  725.   inc  dx
  726.   mov  al, r
  727.   out  dx, al
  728.   mov  al, g
  729.   out  dx, al
  730.   mov  al, b
  731.   out  dx, al
  732. end; {Write index now points to next color}
  733.  
  734. Function getColor(color : Byte) : LongInt; Assembler;
  735. Asm {get DAC color}
  736.   mov  dx, tableReadIndex
  737.   mov  al, color
  738.   out  dx, al
  739.   add  dx, 2
  740.   cld
  741.   xor  bh, bh
  742.   in   al, dx
  743.   mov  bl, al
  744.   in   al, dx
  745.   mov  ah, al
  746.   in   al, dx
  747.   mov  dx, bx
  748. end; {read index now points to next color}
  749.  
  750. Procedure setPalette(color : Byte; num : Word; Var rgb); Assembler;
  751. Asm
  752.   mov   cx, num
  753.   jcxz  @X
  754.   mov   ax, cx
  755.   shl   cx, 1
  756.   add   cx, ax {mul by 3}
  757.   push  ds
  758.   lds   si, rgb
  759.   cld
  760.   mov   dx, tableWriteIndex
  761.   mov   al, color
  762.   out   dx, al
  763.   inc   dx
  764.  @L:
  765.   lodsb
  766.   out   dx, al
  767.   loop  @L
  768.   pop   ds
  769.  @X:
  770. end;
  771.  
  772. Procedure getPalette(color : Byte; num : Word; Var rgb); Assembler;
  773. Asm
  774.   mov   cx, num
  775.   jcxz  @X
  776.   mov   ax, cx
  777.   shl   cx, 1
  778.   add   cx, ax {mul by 3}
  779.   les   di, rgb
  780.   cld
  781.   mov   dx, tableReadIndex
  782.   mov   al, color
  783.   out   dx, al
  784.   add   dx, 2
  785.  @L:
  786.   in    al, dx
  787.   stosb
  788.   loop  @L
  789.  @X:
  790. end;
  791.  
  792. {XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}
  793.  
  794. Function vgaPresent : Boolean; Assembler;
  795. Asm
  796.   mov ah, $F
  797.   int $10
  798.   mov oldMode, al  { save old Gr mode}
  799.   mov ax, $1A00
  800.   int $10          { check For VGA}
  801.   cmp al, $1A
  802.   jne @ERR         { no VGA Bios}
  803.   cmp bl, 7
  804.   jb @ERR          { is VGA or better?}
  805.   cmp bl, $FF
  806.   jnz @OK
  807.  @ERR:
  808.   xor al, al
  809.   jmp @EXIT
  810.  @OK:
  811.   mov al, 1
  812.  @EXIT:
  813. end;
  814.  
  815. Procedure Graphbegin;
  816. Var
  817.   p     : Array [0..255] of tRGB;
  818.   i, j,
  819.   k, l  : Byte;
  820. begin
  821.   Asm
  822.     mov ax, $0013
  823.     int $10
  824.   end;   {set BIOS mode}
  825.  
  826.   l := 0;
  827.   For i := 0 to 5 do
  828.     For j := 0 to 5 do
  829.       For k := 0 to 5 do
  830.       With p[l] do
  831.       begin
  832.         r := (i * 63) div 5;
  833.         g := (j * 63) div 5;
  834.         b := (k * 63) div 5;
  835.         inc(l);
  836.       end;
  837.  
  838.   For i := 216 to 255 do
  839.   With p[i] do
  840.   begin
  841.     l := ((i - 216) * 63) div 39;
  842.     r := l;
  843.     g := l;
  844.     b := l;
  845.   end;
  846.  
  847.   setpalette(0, 256, p);
  848.   color := 0;
  849.  
  850.   Asm
  851.    mov  dx, seqPort
  852.    mov  ax, $0604
  853.    out  dx, ax            { disable chain 4}
  854.    mov  ax, $0100
  855.    out  dx, ax            { synchronous reset asserted}
  856.    dec  dx
  857.    dec  dx
  858.    mov  al, $E3
  859.    out  dx, al            { misc output port at $3C2}
  860.                           { use 25mHz dot clock,  480 lines}
  861.    inc  dx
  862.    inc  dx
  863.    mov  ax, $0300
  864.    out  dx, ax            { restart sequencer}
  865.    mov  dx, CrtcPort
  866.    mov  al, $11
  867.    out  dx, al            { select cr11}
  868.    inc  dx
  869.    in   al, dx
  870.    and  al, $7F
  871.    out  dx, al
  872.    dec  dx                { remove Write protect from cr0-cr7}
  873.    mov  si, offset CrtcRegTable
  874.    mov  cx, CrtcRegLen
  875.    repz outsw             { set Crtc data}
  876.    mov  ax, vxBytes
  877.    shr  ax, 1             { Words per scan line}
  878.    mov  ah, al
  879.    mov  al, $13
  880.    out  dx, ax            { set CrtC offset reg}
  881.   end;
  882.  
  883.   clearGraph;
  884. end;
  885.  
  886. Procedure Graphend; Far;
  887. begin
  888.   ExitProc := exitSave;
  889.   Asm
  890.     mov al, oldMode
  891.     mov ah, 0
  892.     int $10
  893.   end;
  894. end;
  895.  
  896. begin
  897.   CrtcPort   := memw[$40 : $63];
  898.   input1Port := CrtcPort + 6;
  899.   if vgaPresent then
  900.   begin
  901.     ExitSave := exitProc;
  902.     ExitProc := @Graphend;
  903.     Graphbegin;
  904.   end
  905.   else
  906.   begin
  907.     Writeln(^G + 'VGA required.');
  908.     halt(1);
  909.   end;
  910. end.
  911.